#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>   /* Se usa la funcion ATOI */
#include <Ws2tcpip.h>
#include <process.h>

#include <ctype.h>   /* Para pasar de hexa a decimal */
#include <math.h>
#include <time.h>
#include <winbase.h>

#pragma comment (lib, "Ws2_32.lib")
#pragma warning(disable : 4996)

#define RUTA "./configuracion.txt"
#define RUTA_DESCARGA "./descarga/"
#define LARGO_IP 16
#define LARGO_PUERTO 10
#define LARGO_CADENA 300
#define LARGO_NOMBRE_MODULO 50
#define LARGO_MAXIMO_ARCHIVO 10000
#define LARGO_CONFIGURACION 1000
#define LARGO_LINEALOG 350
#define LARGO_ARCHIVO_BUSCADO 256

#define LOGINFO 1
#define LOGDEBUG 2
#define LOGERROR 3
#define LOGFIN 4

#define REQUEST 0x02
#define RESPONSE 0x03

typedef struct {
	char nombreModulo[LARGO_NOMBRE_MODULO];
	char ipLocal[LARGO_IP];
	char ipRemoto[LARGO_IP];
	char puertoRemoto[LARGO_PUERTO];
	char tamanioBuffer[5];
	char rutaDescarga[256];
} TipoConfiguracion;

typedef struct {
		char IDMensaje[16];
		unsigned char IDProtocolo;
		int longitud;
		char nombreArchivo[LARGO_ARCHIVO_BUSCADO];
} TipoMensaje;



typedef struct {
		char ip[16];
		int puerto;
		char* nombre;
}TipoInf_thread;

typedef struct {
		char ip[16];
		int puerto;
		int tamanio;
		char* nombre;
}TipoDatoServidor;


/*Cabeza de msgs del protocolo*/
typedef struct {
	char IDMensaje[16];
	unsigned char ucTipo; /*PING-PONG-QUERY-QUERYHIT*/
	int nLongMensaje;
	} TipoHeaderIPC;

/*Cabecera del Informe*/
/*********************************************/
/*Para implementar los informes en el cliente*/
/*********************************************/
typedef struct ListaInforme{
	struct InfArch *primero;
	struct InfArch *ultimo;
} TipoListaInforme;

typedef struct Informe{
	int iCantDescargas;
	int iTimeTotal;
	struct ListaInforme *listaArchivos;
} TipoInforme;

typedef struct InfArch{
	int iCantBytesArch;
	clock_t ckTimeDescarga;
	__int64 uTimeKernel;
	__int64 uTimeUser;
	DWORD idThread;
	char *sNombre;
	char *sIp;
	struct InfArch *siguiente;
} TipoNodoInfArch;

/*********************************************/
/*********************************************/
typedef struct NodoFile{
	int iPuerto;
	int iIndice;
	long uTamanio;
	char *sNombre;
	char *sIp;
	struct NodoFile *siguiente;
} TipoNodoFile;

typedef struct ListaFile{
	struct NodoFile *primero;
	struct NodoFile *ultimo;
} TipoListaFile;

void func_MostrarMensajeDeAyuda(void);
void func_Errores(int error);
void func_Mensajes(int iMensaje);
int func_DescargarArchivo(SOCKET sockfd, char * nomArch);
SOCKET func_CrearSocket(char * dir_Ip, char *port);
void func_CargarConfiguracion();
void func_LlenadoConfig(char *cadena);
int func_ArmarMensaje(char *archivo,char *strIP, char *strPort, char **mensaje);
int FileLog(int tipo, char *mensaje, char *nombreModulo);
unsigned int __stdcall func_Thread(TipoInf_thread *informacion);
/*void __cdecl func_Thread(TipoInf_thread *informacion);*/
int func_ArchivoErrores (char *sBuffer);
void func_ArmarId (unsigned char *Id);
int Aleatorio ();
TipoMensaje func_ArmaEstructuraMensaje(char *nomArch);
int func_EnviarRequest(TipoMensaje mRequest, SOCKET sock);
int func_RecibirListadoArchivos(SOCKET sockfd,TipoListaFile *listaArchivos);
TipoInf_thread * func_BuscarOpcionFile(int op, TipoListaFile * listaArchivo);
int HexaADec(char *cadena);
int CaracterEnDec(char caracter);
HANDLE func_CrearHiloPorOpcion(int opcion, TipoListaFile * lista_servidores);
void func_LogError();
int atoh(char* buff);
void func_LiberaMemoriaParamThread(TipoInf_thread *vMemoria[],int iCant);
void func_CierraThread(HANDLE *vHilos[],int iCant);
TipoNodoInfArch* CrearElementoInfo(int tamanio);
TipoNodoInfArch * func_CargarNodoInfo(char *sNombre,char *sIp,clock_t ckFinal,int iCantBytes,__int64 *uKernelInicio,__int64 *uUserInicio);
int AgregarElemento(TipoListaInforme *lista, TipoNodoInfArch *elemento);
void func_ObtenerTiempo(__int64 *uTimeKernel, __int64 *uTimeUser);
TipoNodoFile * func_CargarNodoFile(char *sNombre,char *sIp,int iPuerto);
int AgregarElementoFile(TipoListaFile *lista, TipoNodoFile *elemento);
TipoNodoFile* CrearElementoFile(int tamanio);
void EliminarLista(TipoListaFile *lista);
TipoNodoFile * func_ObtenerNodoPorIndice(TipoListaFile *lista,int iIndice);
int GuardarInforme();
__int64 FileTimeToQuadWord(PFILETIME pFileTime);

